package com.hyhy.hycloud.commons.support;

import io.shardingsphere.api.algorithm.sharding.PreciseShardingValue;
import io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
import io.shardingsphere.core.keygen.DefaultKeyGenerator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Configuration;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collection;

/**
 * @author lanpengfei
 * @date 2019-01-04
 */
@Configuration
@ConditionalOnClass({PreciseShardingAlgorithm.class})
public class ShardingConfig {

    @Configuration
    public static class IPSectionKeyGenerator implements InitializingBean {

        @Override
        public void afterPropertiesSet() throws Exception {
            InetAddress address;
            try {
                address = InetAddress.getLocalHost();
            } catch (final UnknownHostException e) {
                throw new IllegalStateException("Cannot get LocalHost InetAddress, please check your network!");
            }
            // 得到IP地址的byte[]形式值
            byte[] ipAddressByteArray = address.getAddress();
            long workerId = 0L;
            //如果是IPV4，计算方式是遍历byte[]，然后把每个IP段数值相加得到的结果就是workerId
            if (ipAddressByteArray.length == 4) {
                for (byte byteNum : ipAddressByteArray) {
                    workerId += byteNum & 0xFF;
                }
                //如果是IPV6，计算方式是遍历byte[]，然后把每个IP段后6位（& 0B111111 就是得到后6位）数值相加得到的结果就是workerId
            } else if (ipAddressByteArray.length == 16) {
                for (byte byteNum : ipAddressByteArray) {
                    workerId += byteNum & 0B111111;
                }
            } else {
                throw new IllegalStateException("Bad LocalHost InetAddress, please check your network!");
            }
            DefaultKeyGenerator.setWorkerId(workerId);
        }
    }


    /**
     * sharding config:
     *  com.hyhy.hycloud.commons.support.ShardingConfig$HospitalShardingStrategy
     */
    @Configuration
    public static class HospitalShardingStrategy implements PreciseShardingAlgorithm<String> {

        @Override
        public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
            for (String table : availableTargetNames) {
                if (table.endsWith(shardingValue.getValue().substring(0, 1))) {
                    return table;
                }
            }
            throw new UnsupportedOperationException();
        }
    }

}
